package core;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;
import core.exception.ModelException;

public class ProductGroupTest {
	ProductGroup _pg;
	@Before
	public void setUp() throws Exception {
		RootStorageUnit.setInstance(null);
		ProductManager.setInstance(null);
		ItemManager.setInstance(null);
		
		Container parent = RootStorageUnit.instance().addContainer("SU1");
		_pg = (ProductGroup) parent.addContainer("PG");
		Container child = _pg.addContainer("child");
		Container c2 = child.addContainer("ccchild");
		_pg.addContainer("otherchild");
		
		Product p1 = new Product(new Barcode("111111111111", BarcodeType.PRODUCT), 
				"my product", new Amount(1,UnitOfMeasurement.gallons),30,0);
		Product p2 = new Product(new Barcode("111111111112", BarcodeType.PRODUCT), 
				"my product", new Amount(1,UnitOfMeasurement.liters),30,0);
		Product p3 = new Product(new Barcode("111111111113", BarcodeType.PRODUCT), 
				"my product", new Amount(1,UnitOfMeasurement.kilograms),30,0);
		Product p4 = new Product(new Barcode("111111111114", BarcodeType.PRODUCT),
				"my product4", new Amount(1, UnitOfMeasurement.count), 30, 0);
		
		ProductManager.instance().addProduct(p1);
		ProductManager.instance().addProduct(p2);
		ProductManager.instance().addProduct(p3);
		ProductManager.instance().addProduct(p4);
		
		// Give child 1 of each product
		ItemManager.instance().addItemToContainer(child, 
				ItemManager.instance().createItem(p1, null));
		ItemManager.instance().addItemToContainer(c2, 
				ItemManager.instance().createItem(p2, null));
		ItemManager.instance().addItemToContainer(child, 
				ItemManager.instance().createItem(p3, null));
		ItemManager.instance().addItemToContainer(child, 
				ItemManager.instance().createItem(p4, null));
		
		// Give parent 2 of each product
		 // Give parent 2 of each product
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p1, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p1, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p2, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p2, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p3, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p3, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p4, null));
		ItemManager.instance().addItemToContainer(_pg,ItemManager.instance().createItem(p4, null));	
	}

	@Test
	public void testGetThreeMonthSupply() {
		assertEquals(new Amount(0,UnitOfMeasurement.count), _pg.getThreeMonthSupply());
	}

	@Test
	public void testCanSetThreeMonthSupply() {
		Amount validA = new Amount(30, UnitOfMeasurement.kilograms);
		Amount validB = new Amount((float)0.655, UnitOfMeasurement.gallons); 
		Amount validC = new Amount(0, UnitOfMeasurement.fluid_ounces);
		Amount invalidA = new Amount(-1,UnitOfMeasurement.liters);
		Amount invalidB = new Amount((float)0.5,UnitOfMeasurement.count);
		
		assertTrue(ProductGroup.canSetThreeMonthSupply(validA));
		assertTrue(ProductGroup.canSetThreeMonthSupply(validB));
		assertTrue(ProductGroup.canSetThreeMonthSupply(validC));
		assertFalse(ProductGroup.canSetThreeMonthSupply(invalidA));
		assertFalse(ProductGroup.canSetThreeMonthSupply(invalidB));
	}

	@Test
	public void testSetThreeMonthSupply() {
		Amount validA = new Amount(30, UnitOfMeasurement.kilograms);
		Amount validB = new Amount((float)0.655, UnitOfMeasurement.gallons); 
		Amount validC = new Amount(0, UnitOfMeasurement.fluid_ounces);
		
		_pg.setThreeMonthSupply(validA);
		assertEquals(validA, _pg.getThreeMonthSupply());
		
		_pg.setThreeMonthSupply(validB);
		assertEquals(validB, _pg.getThreeMonthSupply());
		
		_pg.setThreeMonthSupply(validC);
		assertEquals(validC,_pg.getThreeMonthSupply());
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testSetThreeMonthSupplyException1() {
		Amount invalidA = new Amount(-1,UnitOfMeasurement.liters);
		_pg.setThreeMonthSupply(invalidA);
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void testSetThreeMonthSupplyException2() {
		Amount invalidB = new Amount((float)0.5,UnitOfMeasurement.count);
		_pg.setThreeMonthSupply(invalidB);
	}	

	@Test
	public void testGetAmountNeededForNMonthSupply() throws ModelException {
		Amount threeMonth = new Amount((float)14.3562, UnitOfMeasurement.liters);
		Amount zero = new Amount(0,UnitOfMeasurement.liters);
		_pg.setThreeMonthSupply(threeMonth);
		
		assertEquals(zero.getQuantity(),_pg.getAmountNeededForNMonthSupply(3).getQuantity(), 0.1);
		assertEquals(zero.getQuantity(),_pg.getAmountNeededForNMonthSupply(1).getQuantity(), 0.1);
		assertEquals(threeMonth.getQuantity(),_pg.getAmountNeededForNMonthSupply(6).getQuantity(),
				0.1);
		
		Amount count = new Amount(3, UnitOfMeasurement.count);
		_pg.setThreeMonthSupply(count);
		assertEquals(zero.getQuantity(),_pg.getAmountNeededForNMonthSupply(1).getQuantity(),0.1);
		assertEquals(zero.getQuantity(),_pg.getAmountNeededForNMonthSupply(3).getQuantity(), 0.1);
		assertEquals(count.getQuantity(), _pg.getAmountNeededForNMonthSupply(6).getQuantity(), 
				0.1);
	}
	
	@Test(expected=ModelException.class)
	public void testGetAmountNeededForNMonthSupplyException() throws ModelException {
		_pg.getAmountNeededForNMonthSupply(0);
	}

	@Test
	public void testCanGetAmountNeededForNMonthSupply() {
		assertTrue(_pg.canGetAmountNeededForNMonthSupply(1));
		assertTrue(_pg.canGetAmountNeededForNMonthSupply(50));
		
		assertFalse(_pg.canGetAmountNeededForNMonthSupply(0));
		assertFalse(_pg.canGetAmountNeededForNMonthSupply(-1));
	}

}
